﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using System.Text;
using System.IO;

namespace Htse.Blue.Helpers
{
	public class JsonDropDownList
	{
		private HtmlHelper helper;
		private string selectionLabel;
		private string selectionLabelValue;
		private string id;
		private int? selectedId;
		private string formElementName;
		private string loadDataController;
		private string loadDataAction;
		private string changeUrl;
		private string changeDiv;
		private IDictionary<string, object> htmlAttributes;

		internal JsonDropDownList(HtmlHelper helper, IDictionary<string, object> htmlAttributes)
		{
			this.helper = helper;
			this.htmlAttributes = htmlAttributes;
		}

		/// <summary>
		/// Specifies the id of the DropDownList
		/// </summary>
		/// <param name="id">id</param>
		/// <returns></returns>
		public JsonDropDownList Id(string id)
		{
			this.id = id;

			return this;
		}

		public JsonDropDownList FormElementName(string formElementName)
		{
			this.formElementName = formElementName;

			return this;
		}

		/// <summary>
		/// Specifies the label to display as the first element of the list. The value is an empty string by default.
		/// </summary>
		/// <param name="selectionLabel"></param>
		/// <returns></returns>
		public JsonDropDownList SelectionLabel(string text, string value)
		{
			this.selectionLabel = text;
			this.selectionLabelValue = value;

			return this;
		}

		public JsonDropDownList SelectedId(int id)
		{
			this.selectedId = id;

			return this;
		}

		/// <summary>
		/// Specifies the controller and the action that provides the json data to the DropDownList
		/// </summary>
		/// <param name="controller">Controller name</param>
		/// <param name="action">Action name</param>
		/// <returns></returns>
		public JsonDropDownList LoadJsonDataFrom(string controller, string action)
		{
			this.loadDataController = controller;
			this.loadDataAction = action;

			return this;
		}

		/// <summary>
		/// Specifies what url to call when the selected value changes.
		/// </summary>
		/// <param name="url">
		///	The url to call.
		///	The selecte value will be formatted into the string.
		///	Use the following syntax: /controller/action/?parameter={0}
		///	For example the url /Home/GetValues/?Color={0} will call the url /Home/GetValues/?Color=3 when the selected value is 3
		/// </param>
		/// <returns></returns>
		public JsonDropDownList OnChangeCallUrl(string url)
		{
			this.changeUrl = url;

			return this;
		}

		/// <summary>
		/// Specifies the id of the div to update when the selected value changes.
		/// </summary>
		/// <param name="div">The id of the div</param>
		/// <returns></returns>
		public JsonDropDownList OnChangeUpdateDiv(string div)
		{
			this.changeDiv = div;

			return this;
		}

		private string Render()
		{
			TagBuilder optionTag = new TagBuilder("option");

			if (selectionLabel != null)
			{
				optionTag.MergeAttribute("value", selectionLabelValue ?? string.Empty);
				optionTag.SetInnerText(selectionLabel);
			}

			TagBuilder selectTag = new TagBuilder("select");
			selectTag.MergeAttribute("id", id);
			selectTag.MergeAttribute("name", formElementName);
			selectTag.MergeAttributes<string, object>(htmlAttributes);

			if (selectionLabel != null)
			{
				selectTag.InnerHtml = optionTag.ToString(TagRenderMode.Normal);
			}

			StringBuilder sb = new StringBuilder();

			sb.Append(selectTag.ToString(TagRenderMode.Normal));

			sb.AppendLine("<script language=\"javascript\" type=\"text/javascript\">");
			sb.AppendLine("$(document).ready(function() {");
			sb.AppendLine("$.getJSON(\"/" + loadDataController + "/" + loadDataAction + "\", null, function(data) {");
			sb.AppendLine(string.Format("$(\"#{0}\").fillSelect(data);", id));

			if (selectedId.HasValue)
			{
				sb.AppendLine(string.Format("$(\"#{0}\").val({1});", id, selectedId));
			}
			else
			{
				sb.AppendLine(string.Format("$(\"#{0}\").val({1});", id, selectionLabelValue));
			}

			sb.AppendLine("});");
			sb.AppendLine(string.Format("$('#{0}').change(function() {{", id));
			sb.AppendLine(string.Format("var url = String.format(\"{0}\", $(\"#{1}\").val());", changeUrl, id));
			sb.AppendLine(string.Format("$(\"#{0}\").load(url);", changeDiv));
			sb.AppendLine("});");
			sb.AppendLine("});");
			sb.AppendLine("</script>");

			return sb.ToString();
		}

		public override string ToString()
		{
			return Render();
		}
	}

	public static class JsonDropDownListHelper
	{
		/// <summary>
		/// DropDownList that load data from a Json Action and call an action whenever it changes.
		/// ATTENTION: Make sure to include the jquery select plugin contained in file jquery.select.js
		/// </summary>
		/// <param name="htmlHelper"></param>
		/// <param name="htmlAttributes"></param>
		/// <returns></returns>
		public static JsonDropDownList JsonDropDownList(
			this HtmlHelper htmlHelper,
			IDictionary<string, object> htmlAttributes)
		{
			return new JsonDropDownList(htmlHelper, htmlAttributes);
		}

		/// <summary>
		/// DropDownList that load data from a Json Action and call an action whenever it changes.
		/// ATTENTION: Make sure to include the jquery select plugin contained in file jquery.select.js</summary>
		/// <param name="htmlHelper"></param>
		/// <param name="htmlAttributes"></param>
		/// <returns></returns>
		public static JsonDropDownList JsonDropDownList(
			this HtmlHelper htmlHelper,
			object htmlAttributes)
		{
			return JsonDropDownList(htmlHelper, ((IDictionary<string, object>)new RouteValueDictionary(htmlAttributes)));
		}

		/// <summary>
		/// DropDownList that load data from a Json Action and call an action whenever it changes.
		/// ATTENTION: Make sure to include the jquery select plugin contained in file jquery.select.js</summary>
		/// <param name="htmlHelper"></param>
		/// <returns></returns>
		public static JsonDropDownList JsonDropDownList(
			this HtmlHelper htmlHelper)
		{
			return JsonDropDownList(htmlHelper, null);
		}
	}
}
